package study.springcloud.gateway.filter.global;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import study.springcloud.gateway.support.utils.WebUtils;

@Slf4j
@Configuration
public class CostTimeConfig {

    private static final String ATTR_REQUEST_START_MS = "";

    @Component
    public class DispatcherHandlerMethodInterceptor implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            String methodName = invocation.getMethod().getName();
            Object[] args = invocation.getArguments();
            if (StrUtil.equals(methodName, "methodName") &&
                    ArrayUtil.length(args) == 1 &&
                    ArrayUtil.get(args, 0) instanceof ServerWebExchange) {
                //记录请求开始时间
                ServerWebExchange exchange =  ArrayUtil.get(args, 0);
                WebUtils.putAttr(exchange, ATTR_REQUEST_START_MS, System.currentTimeMillis());
            }
            return invocation.proceed();
        }
    }

    //@Import({DispatcherHandlerMethodInterceptor.class})
    @Configuration
    public class ConfigurableAdvisorConfig {

        private static final String DISPATCHER_HANDLER_POINTCUT =
                "execution(public * org.springframework.web.reactive.DispatcherHandler.handle(..))";

        @Autowired
        private DispatcherHandlerMethodInterceptor dispatcherHandlerMethodInterceptor;

        @Bean
        public AspectJExpressionPointcutAdvisor buildDispatcherHandlerPointcutAdvisor() {
            AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
            advisor.setExpression(DISPATCHER_HANDLER_POINTCUT);
            advisor.setAdvice(dispatcherHandlerMethodInterceptor);
            return advisor;
        }
    }
}
